/****************************************************************************
 *  QLyrics - A simple lyrics viewer.                                       *
 *  Copyright (C) 2008  hsys <hanshuiys@gmail.com>                          *
 *                                                                          *
 *  This program is free software; you can redistribute it and/or modify    *
 *  it under the terms of the GNU General Public License as published by    *
 *  the Free Software Foundation; either version 3 of the License, or       *
 *  (at your option) any later version.                                     *
 *                                                                          *
 *  This program is distributed in the hope that it will be useful,         *
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of          *
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the           *
 *  GNU General Public License for more details.                            *
 *                                                                          *
 *  You should have received a copy of the GNU General Public License       *
 *  along with this program; if not, write to the Free Software Foundation, *
 *  Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301  USA       *
 ****************************************************************************/

#include "player.h"
#include <cstdio>
#include <ctime>

Player* Player::sm_inst = NULL;

/*
const Player::ResponseEvent Player::responseForRequest[8] = {
    Player::ResponseExit,       // no use
    Player::ResponseTitle,
    Player::ResponseAlbum,
    Player::ResponseArtist,
    Player::ResponseLength,
    Player::ResponseFilename,
    Player::ResponseTime,
    Player::ResponseExit
};
*/

void Player::buildInstance(QObject* parent) {
    if (sm_inst == NULL)
        sm_inst = new Player(parent);
};

Player* Player::getInstance() {
    return sm_inst;
};

Player::Player(QObject* parent) : QObject(parent) {
    m_status = Closed;
    m_offset = 0;
    memset(isWaiting, false, sizeof(isWaiting));
    connect(&m_pipe, SIGNAL(readyRead()), SLOT(readFromPlayer()));
};

Player::~Player() {
    if (m_status != Closed)
        sendRequestEvent(RequestExit);
};

bool Player::connectToPlayer(QString serverName) {
    // already connected
    if (m_pipe.state() == QLocalSocket::ConnectedState)
        return true;

    m_pipe.connectToServer(serverName);
    if (!m_pipe.waitForConnected(10000))
        return false;

    // connected
    m_status = Idle;
    return true;
};

void Player::updatePlaybackTime() {
    sendRequestEvent(RequestTime, true);
};

void Player::sendRequestEvent(RequestEvent e, bool blocking) {
    int retry = isWaiting[e] ? 1 : 0;
    isWaiting[e] = true;
    do {
        if (retry == 0) {
            /*FILE* log = fopen("qlyrics.log", "a");
            time_t t = time(NULL);
            char* tm = ctime(&t);
            tm[strlen(tm) - 2] = '\0';
            fprintf(log, "[%s] >>> Send Request: %d\n", tm, (int)e);
            fclose(log);
*/
            m_pipe.write(QByteArray::number((int)e).append('\n'));
            m_pipe.flush();
        };
        retry = (retry + 1) % 3;
        m_pipe.waitForReadyRead(200);
        readFromPlayer();
    } while (blocking && isWaiting[e]);
};

const Track& Player::getTrack() {
    sendRequestEvent(RequestArtist, true);
    sendRequestEvent(RequestTitle, true);
    sendRequestEvent(RequestAlbum, true);
    sendRequestEvent(RequestFilename, true);
    return m_track;
};

void Player::readFromPlayer() {
    while (m_pipe.canReadLine()) {
        ResponseEvent eventID;
        QString param;

        QString line = QString::fromUtf8(m_pipe.readLine().data());

        /*FILE* log = fopen("qlyrics.log", "a");
        time_t t = time(NULL);
        char* tm = ctime(&t);
        tm[strlen(tm) - 2] = '\0';
        fprintf(log, "[%s] <<< Got Response: %s", tm, line.toUtf8().data());
        fclose(log);
*/
        const char requestDelimiter = ' ';
        eventID = ResponseEvent(line.mid(0, line.indexOf(requestDelimiter)).toInt());
        if (line.indexOf(requestDelimiter) != -1)
            param = line.mid(line.indexOf(requestDelimiter) + 1).trimmed();

        if (eventID < (sizeof(isWaiting) / sizeof(bool)) && eventID >= 0)
            isWaiting[eventID] = false;

        parseEvent(eventID, param);
    };
};

void Player::parseEvent(ResponseEvent e, QString param) {
    switch (e) {
    case ResponseExit:
        emit exit();
        return;
    case ResponseStatusChange:
        m_status = Status(param.toInt()); 
        emit statusChanged(m_status);
        break;
    case ResponseTrackChange:
        m_offset = 0;
        emit trackChanged();
        break;
    case ResponseConfigure:
        emit configure();
        break;
    case ResponseTitle:
        m_track.title = param;
        break;
    case ResponseAlbum:
        m_track.album = param;
        break;
    case ResponseArtist:
        m_track.artist = param;
        break;
    case ResponseFilename:
        m_track.url = param;
        break;
    case ResponseLength:
        break;
    case ResponseTime:
        m_offset = param.toInt();
        emit timeChanged(m_offset);
        break;
    };
};

